package cn.tedu.submarine;

import com.sun.xml.internal.bind.v2.runtime.output.ForkXmlOutput;

import javax.swing.*;
import javax.swing.plaf.nimbus.State;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.*;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.ObjIntConsumer;

//整个游戏窗口
public class World extends JPanel {
    public static final int WIDTH = 641;
    public static final int HEIGHT = 479;
    public static final int RUNNING=1;
    public static final int PAUSE=2;
    public static final int GAME_OVER=0;
    public int state=RUNNING;
    private Battleship ship = new Battleship();
    private Property[] submarines = {};
    private Mine[] mines = {};
    private Bomb[] bombs = {};

    public Property nextSubmarine(){
        Random random=new Random();
        int type=random.nextInt(20);
        if (type<10){
            return new ObserveSubmarine();
        }else if (type<15){
            return new TorpedoSubmarine();
        }else {
            return new MineSubmarine();
        }
    }
    //出现潜艇对象
    private int subEnterIndex=0;
    public void submarinesEnterActon(){//每10毫秒走一次
        subEnterIndex++;//每10毫秒+1
        if(subEnterIndex%40==0){//每400（40*10）毫秒运行一次
            Property pro=nextSubmarine();
            submarines = Arrays.copyOf(submarines,submarines.length+1);//扩容
            submarines[submarines.length-1]=pro;
        }
    }

    //出现水雷对象
    private int minEnterIndex=0;
    public void minEnterAction(){
        minEnterIndex++;
        if(minEnterIndex%100==0){
            for(int i=0;i<submarines.length;i++){
                if(submarines[i] instanceof MineSubmarine){
                    MineSubmarine ms=(MineSubmarine)submarines[i];
                    Mine m=ms.shootMine();
                    mines=Arrays.copyOf(mines,mines.length+1);
                    mines[mines.length-1]=m;
                }
            }
        }
    }
    public void deleteAction(){
        for(int i=0;i<submarines.length;i++){
            if(submarines[i].Delete()||submarines[i].isDead()){
                submarines[i]=submarines[submarines.length-1];
                submarines=Arrays.copyOf(submarines,submarines.length-1);
            }
        }
        for (int i=0;i<mines.length;i++){
            if (mines[i].Delete()||mines[i].isDead()){
                mines[i]=mines[mines.length-1];
                mines=Arrays.copyOf(mines,mines.length-1);
            }
        }
        for(int i=0;i<bombs.length;i++){
            if(bombs[i].Delete()||bombs[i].isDead()){
                bombs[i]=bombs[bombs.length-1];
                bombs=Arrays.copyOf(bombs,bombs.length-1);
            }
        }
    }
    //爆炸判定
    int score=0;  //玩家得分
    int life=0;   //玩家命数
    public void BombsBangAction(){
        for (int i = 0; i < bombs.length; i++) {
            Bomb b=bombs[i];
            for (int j = 0; j < submarines.length; j++) {
                Property sub=submarines[j];
                if(b.isLive() && sub.isLive() && sub.isHit(b)) {
                    b.goDead();
                    sub.goDead();
                    if(sub instanceof EnemyScore){//如果被撞对象为分
                        EnemyScore es=(EnemyScore)sub;//将被撞对象强转为接口
                        score+=es.getScore();
                    }
                    if(sub instanceof EnemyLife){
                        EnemyLife e1=(EnemyLife)sub;
                        int num=e1.getLife();
                        ship.addLife(num);
                    }
                }
            }
        }
    }
    //水雷爆炸
    public void mineBangAction(){
        for (int i = 0; i < mines.length; i++) {
            Mine m=mines[i];
            if (m.isLive()&&ship.isLive()&&m.isHit(ship)){
                m.goDead();
                ship.subtractLife();
            }
        }
    }
    //移动指令
    public void moveAction(){
        for(int i=0;i<submarines.length;i++){
            submarines[i].move(); //潜艇动
        }
        for (int i=0;i<mines.length;i++){
                mines[i].move();  //水雷动
        }
        for (int i=0;i<bombs.length;i++){
            bombs[i].move();      //炸弹动
        }
    }
    //检测游戏结束
    public void checkGameOverAction(){
        if(ship.getLife()<=0){
            state=GAME_OVER;
        }
    }


    //启动程序的执行
    public void action(){
        KeyAdapter k=new KeyAdapter() {
            //重写keyPressed键盘按下事件
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode()==KeyEvent.VK_SPACE){
                    Bomb b=ship.BombShoot();
                    bombs=Arrays.copyOf(bombs,bombs.length+1);
                    bombs[bombs.length-1]=b;
                }
                if(e.getKeyCode()==KeyEvent.VK_LEFT){
                    ship.moveLeft();
                }
                if(e.getKeyCode()==KeyEvent.VK_RIGHT){
                    ship.moveRight();
                }
                if(state==RUNNING && e.getKeyCode()==KeyEvent.VK_P){
                    state=PAUSE;
                    int r=JOptionPane.showConfirmDialog(
                            World.this,"保存游戏吗？");
                if(r==JOptionPane.YES_OPTION){
                    SaveInfo saveInfo=new SaveInfo(ship,submarines,mines,bombs,subEnterIndex,score);
                    try{
                    FileOutputStream fos=new FileOutputStream("sava.obj");
                    ObjectOutputStream oos=new ObjectOutputStream(fos);
                    oos.writeObject(saveInfo);
                    oos.close();
                    System.exit(0);
                    }catch (IOException ex){ }

                }
                state=RUNNING;
                }
                if(state==PAUSE && e.getKeyCode()==KeyEvent.VK_P){
                    state=RUNNING;
                }
            }
        };
        this.addKeyListener(k);//添加侦听

        Timer timer=new Timer();//定时器的对象
        int interval=10;//定时间隔（以毫秒为单位）
        timer.schedule(new TimerTask() {
            @Override
            public void run() {//定时干的事，每10毫秒自动执行
                submarinesEnterActon();   //潜艇（侦察，鱼类，水雷）入场
                minEnterAction();         //水雷入场
                moveAction();            //海洋对象移动
                BombsBangAction();
                mineBangAction();
                deleteAction();
                checkGameOverAction();
                repaint();//重画(重新调用paint()方法)
            }
        }, interval, interval);//计划表/日程表
    }

    public void paint(Graphics g) {
        switch (state) {
            case GAME_OVER:
                Images.gameover.paintIcon(null,g,0,0);
                break;
            case PAUSE:
                Images.mine.paintIcon(null,g,200,200);
                break;
            case RUNNING:
                Images.sea.paintIcon(null, g, 0, 0);
            //第一个用到Images类时，会将Images.class加载到方法区中，
            //同时将静态变量分配到方法区中，同时自动执行静态块。
                ship.paintImage(g);
                for (int i = 0; i < submarines.length; i++) {
                submarines[i].paintImage(g);
            }
                for (int i = 0; i < mines.length; i++) {
                mines[i].paintImage(g);
            }
                for (int i = 0; i < bombs.length; i++) {
                bombs[i].paintImage(g);
            }
                g.drawString("SCORE: " + score, 200, 50);
                g.drawString("LIFE: " + ship.getLife(), 400, 50);
        }
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        JFrame frame = new JFrame();
        World world = new World(); //给World类中的实例变量赋值
        world.setFocusable(true);
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH + 16, HEIGHT + 39);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        /*
        * 是否需要读取存档
        */
        File file=new File("sava.obj");
        if(file.exists()){
            int r=JOptionPane.showConfirmDialog(world,"是否读取存档");
            if(r==JOptionPane.YES_OPTION){
                FileInputStream fis=new FileInputStream(file);
                ObjectInputStream ois=new ObjectInputStream(fis);
                SaveInfo saveInfo=(SaveInfo) ois.readObject();
                world.bombs=saveInfo.getBombs();
                world.score=saveInfo.setScore();
                world.mines=saveInfo.getMines();
                world.minEnterIndex=saveInfo.getMinEnterIndex();
                world.submarines=saveInfo.getSubmarines();
                world.subEnterIndex=saveInfo.getSubEnterIndex();
                world.ship=saveInfo.getShip();
                ois.close();
            }
        }

        world.action();//启动程序的执行

    }
}
